package postgres

import (
	"auth/model"
	"auth/model/entity"
)

var Dept = &dept{}

type dept struct{}

func (a *dept) Create(m *entity.Dept) (int64, error) {
	err := db.Create(m).Error
	return m.DeptId, err
}

func (a *dept) Find(id int64) (*entity.Dept, error) {
	e := &entity.Dept{}
	err := db.Model(&entity.Dept{}).Find(&e, id).Error
	return e, err
}

func (a *dept) FindByParameter(in *model.DeptInfo) (*entity.Dept, error) {
	var (
		err    error
		q      = db.Model(&entity.Dept{})
		entity entity.Dept
	)
	if in.ParentId > 0 {
		q = q.Where("parent_id = ?", in.ParentId)
	}
	err = q.First(&entity).Error
	return &entity, err
}

func (a *dept) GetChildrenByDeptId(deptId int64) ([]int64, error) {
	var (
		err     error
		deptIds = make([]int64, 0)
	)
	sql := " WITH RECURSIVE le (dept_id,parent_id) as " +
		"( " +
		"select dept_id,parent_id from depts where dept_id= ?" +
		" union all" +
		" select e2.dept_id,e2.parent_id from depts e2,le e3 where e3.dept_id=e2.parent_id  " +
		")" +
		" select dept_id from le"
	err = db.Raw(sql, deptId).Scan(&deptIds).Error
	return deptIds, err
}

func (a *dept) IsExistDeptName(notEqId int64, deptName string) error {
	var (
		err    error
		q      = db.Model(&entity.Dept{})
		entity entity.Dept
	)
	if deptName != "" {
		q = q.Where("dept_name = ?", deptName)
	}
	if notEqId > 0 {
		q = q.Where("dept_id <> ?", notEqId)
	}
	err = q.First(&entity).Error
	return err
}

func (a *dept) GetBaseDeptTreeMap() ([]*entity.Dept, error) {
	var (
		err      error
		allDepts []*entity.Dept
	)
	err = db.Order("sort").Find(&allDepts).Error
	return allDepts, err
}

func (a *dept) Update(id int64, dict map[string]interface{}) error {
	return db.Model(&entity.Dept{}).Where("dept_id = ?", id).Updates(dict).Error
}

func (a *dept) Delete(id int64) error {
	return db.Delete(&entity.Dept{}, id).Error
}

func (a *dept) List(in *model.DeptListRequest) (int, []*entity.Dept, error) {
	var (
		q     = db.Model(&entity.Dept{})
		err   error
		total int64
		depts []*entity.Dept
	)

	if err = q.Count(&total).Error; err != nil {
		return 0, nil, err
	}
	if err = q.Limit(in.Size).Offset((in.Index - 1) * in.Size).Find(&depts).Error; err != nil {
		return 0, nil, err
	}
	return int(total), depts, nil
}
